package bll

import (
	"encoding/json"
	"encoding/xml"
	"fmt"
	"net/http"
	"strconv"

	payUtil "jgt-wallet/src/gopay/util"
	"jgt-wallet/src/gopay/wechat"
	"jgt-wallet/src/schema"
	"jgt-wallet/src/util"
)

// 微信APP
type WechatApp struct {
	OrderBll *Order `inject:""`
}

// Pay 支付
func (a *WechatApp) Pay(key string, params *schema.WechatAppPayParams) (map[string]string, error) {

	var (
		client *wechat.AppClient
		fdata  map[string]string
		old    *schema.OrderQueryResult
		order  = new(schema.Order)
		charge = new(wechat.Charge)
		err    error
	)

	//检验订单可支付性
	old, err = a.OrderBll.GetOrderResult(params.OrderID)
	if err != nil {
		return nil, err
	}
	if old.Result == schema.RESULT_SUCCESS {
		return nil, fmt.Errorf("订单已支付")
	} else if old.Result == schema.RESULT_ERROR {
		return nil, fmt.Errorf("订单异常,请联系客服")
	}

	order.PayType = schema.PAY_TYPE_WECHAT_APP
	order.Client = key

	order.RecordID = util.GenerateRecordID()
	order.OrderID = params.OrderID
	order.Price = params.Price
	order.Des = params.Describe
	order.Tag = params.Tag

	client = wechat.GetAppClient(key)
	if client == nil {
		return nil, fmt.Errorf("未找到指定支付宝APP客户端")
	}

	charge.TradeNum = order.RecordID
	charge.Describe = params.Describe
	charge.MoneyFee = params.Price
	charge.CallbackURL = params.Url

	fdata, err = client.Pay(charge)
	if err != nil {
		return nil, err
	}

	order.PayData = fmt.Sprint(fdata)
	err = a.OrderBll.CreateOrder(order)
	if err != nil {
		return nil, err
	}

	return fdata, nil
}

// Check 同步回调
func (a *WechatApp) Check(key string, orderId string) (*schema.WechatAppCheckResult, error) {
	var (
		recordId string
		order    *schema.Order
		client   *wechat.AppClient
		data     *wechat.WeChatQueryResult
		result   = new(schema.WechatAppCheckResult)
		xmlbs    []byte
		err      error
	)

	order, err = a.OrderBll.GetOrder(recordId)
	if err != nil {
		return result, err
	}
	if order == nil {
		return result, fmt.Errorf("支付订单不存在")
	}

	if order.Client == key {
		client = wechat.GetAppClient(order.Client)
	}

	if client == nil {
		return result, fmt.Errorf("支付终端不存在")
	}

	data, err = client.QueryOrder(order.RecordID)
	if err != nil {
		return result, err
	}
	if data == nil {
		return result, fmt.Errorf("支付结果查询失败")
	}
	xmlbs, err = xml.Marshal(data)

	if data.ResultCode == wechat.RESULT_SUCCESS && data.ReturnCode == wechat.RESULT_SUCCESS {
		if data.TradeState == wechat.RESULT_SUCCESS {
			result.Result = schema.RESULT_SUCCESS
			result.OrderID, err = a.OrderBll.CheckOrder(data.OutTradeNO, string(xmlbs), schema.CHECK_STATUS_SUCCESS)
		} else {
			result.Result = schema.RESULT_FAIL
			result.OrderID, err = a.OrderBll.CheckOrder(data.OutTradeNO, string(xmlbs), schema.CHECK_STATUS_FAIL)
		}
	} else {
		result.Result = schema.RESULT_ERROR
		result.OrderID, err = a.OrderBll.CheckOrder(data.OutTradeNO, string(xmlbs), schema.CHECK_STATUS_ERROR)
	}

	result.RecordID = data.OutTradeNO
	result.OrderID = order.OrderID
	if data.TotalFee != "" {
		result.Price, err = strconv.ParseInt(data.TotalFee, 10, 0)
	}
	result.Msg = data.ReturnMsg

	return result, err
}

// CallBack 异步回调
func (a *WechatApp) CallBack(key string, w http.ResponseWriter, r *http.Request) error {
	var (
		order  *schema.Order
		data   *wechat.WeChatPayResult
		client *wechat.AppClient
		err    error
	)

	client = wechat.GetAppClient(key)
	if client == nil {
		w.Write([]byte("error"))
		return fmt.Errorf("未找到指定支付宝APP客户端")
	}

	data, err = client.CallBack(w, r)
	if err != nil {
		return err
	}

	if data.ReturnCode == wechat.RESULT_SUCCESS {
		order, err = a.OrderBll.GetOrder(data.OutTradeNO)
		if err != nil {
			return err
		}
		if data.ResultCode == wechat.RESULT_SUCCESS &&
			payUtil.ParseMoneyFen(data.TotalFee) == order.Price {

			err = a.OrderBll.CallbackOrder(data.OutTradeNO, data.TransactionID, fmt.Sprint(data),
				schema.CALLBACK_STATUS_SUCCESS, payUtil.ParseMoneyFen(data.TotalFee))

		} else if data.ResultCode == wechat.RESULT_FAIL {

			err = a.OrderBll.CallbackOrder(data.OutTradeNO, data.TransactionID, fmt.Sprint(data),
				schema.CALLBACK_STATUS_FAIL, payUtil.ParseMoneyFen(data.TotalFee))

		}
	}

	return err
}

// QueryOrderResult 查询订单支付结果
func (a *WechatApp) QueryOrderResult(recordId string) error {
	var (
		data   *wechat.WeChatQueryResult
		client *wechat.AppClient
		order  *schema.Order
		item   = new(schema.Order)
		bs     []byte
		err    error
	)

	order, err = a.OrderBll.GetOrder(recordId)
	if err != nil {
		return err
	}
	if order.PayType != schema.PAY_TYPE_WECHAT_APP {
		return fmt.Errorf("支付方式错误")
	}
	client = wechat.GetAppClient(order.Client)
	if client == nil {
		return fmt.Errorf("找不到指定客户端")
	}
	item.RecordID = order.RecordID

	data, err = client.QueryOrder(recordId)

	bs, err = json.Marshal(data)

	if err != nil {
		item.QueryData = err.Error()
	} else {
		item.QueryData = string(bs)
		if data.ResultCode == wechat.RESULT_SUCCESS {
			item.TradeID = data.OutTradeNO
			if data.TradeState == wechat.RESULT_SUCCESS ||
				data.TradeState == wechat.RESULT_CLOSED {
				item.Status = schema.ORDER_STATUS_SUCCESS
				item.RealPrice = payUtil.ParseMoneyFen(data.TotalFee)
			} else if data.TradeState == wechat.RESULT_PAYERROR {
				item.Status = schema.ORDER_STATUS_FAIL
			} else if data.TradeState == wechat.RESULT_NOTPAY ||
				data.TradeState == wechat.RESULT_REVOKED {
				item.Status = schema.ORDER_STATUS_CANCEL
			} else if data.TradeState == wechat.RESULT_REFUND {
				item.Status = schema.ORDER_STATUS_REFUND
			} else {
				item.Status = schema.ORDER_STATUS_ERROR
			}
		} else {
			item.Status = schema.ORDER_STATUS_ERROR
		}
	}
	return a.OrderBll.UpdateOrder(item)
}
